﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SixLabors.ImageSharp;

namespace MyWatermark
{
    public static class BitConverterEx
    {
        // 字节序处理模式
        public enum Endianness
        {
            LittleEndian,
            BigEndian
        }

        /* 基本转换方法 */

        /// <summary>
        /// 字节转比特数组（固定8位）
        /// </summary>
        public static bool[] ByteToBits(byte b, Endianness endian = Endianness.BigEndian)
        {
            var bits = new bool[8];
            for (int i = 0; i < 8; i++)
            {
                int shift = (endian == Endianness.BigEndian) ? (7 - i) : i;
                bits[i] = (b & (1 << shift)) != 0;
            }
            return bits;
        }

        /// <summary>
        /// 比特数组转字节（自动补零）
        /// </summary>
        public static byte BitsToByte(IEnumerable<bool> bits, Endianness endian = Endianness.BigEndian)
        {
            byte result = 0;
            var bitArray = bits.Take(8).ToArray();
            int len = bitArray.Length;

            for (int i = 0; i < 8; i++)
            {
                int srcPos = (endian == Endianness.BigEndian) ? (7 - i) : i;
                bool bit = (srcPos < len) ? bitArray[srcPos] : false;
                if (bit) result |= (byte)(1 << i);
            }
            return result;
        }

        /* 扩展方法：数值类型转换 */

        // 整数转比特流（自动4字节）
        public static bool[] IntToBits(int value, Endianness endian = Endianness.BigEndian)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            if (endian == Endianness.BigEndian != BitConverter.IsLittleEndian)
                Array.Reverse(bytes);

            return bytes.SelectMany(b => ByteToBits(b, endian)).ToArray();
        }

        // 比特流转整数（至少32位）
        public static int BitsToInt(IEnumerable<bool> bits, Endianness endian = Endianness.BigEndian)
        {
            byte[] bytes = BitsToBytes(bits.Take(32), endian);
            if (bytes.Length < 4)
                throw new ArgumentException("至少需要32位");

            if (endian == Endianness.BigEndian != BitConverter.IsLittleEndian)
                Array.Reverse(bytes, 0, 4);

            return BitConverter.ToInt32(bytes, 0);
        }

        /* 批量转换方法 */

        // 字节数组转比特流
        public static bool[] BytesToBits(byte[] bytes, Endianness endian = Endianness.BigEndian)
        {
            return bytes.SelectMany(b => ByteToBits(b, endian)).ToArray();
        }

        // 比特流转字节数组（自动补齐8的倍数）
        public static byte[] BitsToBytes(IEnumerable<bool> bits, Endianness endian = Endianness.BigEndian)
        {
            var bitList = bits.ToList();
            int byteCount = (bitList.Count + 7) / 8;

            byte[] result = new byte[byteCount];
            for (int i = 0; i < byteCount; i++)
            {
                var chunk = bitList.Skip(i * 8).Take(8);
                result[i] = BitsToByte(chunk, endian);
            }
            return result;
        }

        /* 字符串专用转换 */

        // UTF8字符串转比特流（带BOM头）
        public static bool[] StringToBits(string text, Endianness endian = Endianness.BigEndian)
        {
            byte[] bom = Encoding.UTF8.GetPreamble();
            byte[] data = Encoding.UTF8.GetBytes(text);
            return BytesToBits(bom.Concat(data).ToArray(), endian);
        }

        // 比特流转UTF8字符串（自动识别BOM）
        public static string BitsToString(IEnumerable<bool> bits, Endianness endian = Endianness.BigEndian)
        {
            byte[] allBytes = BitsToBytes(bits, endian);

            // 检测并跳过BOM
            int startIndex = 0;
            if (allBytes.Length >= 3 &&
                allBytes[0] == 0xEF &&
                allBytes[1] == 0xBB &&
                allBytes[2] == 0xBF)
            {
                startIndex = 3;
            }

            return Encoding.UTF8.GetString(allBytes, startIndex, allBytes.Length - startIndex);
        }

        /* 尺寸头专用转换 */

        // 尺寸结构体转比特流
        public static bool[] SizeToBits(Size size, Endianness endian = Endianness.BigEndian)
        {
            return IntToBits(size.Width, endian)
                .Concat(IntToBits(size.Height, endian))
                .ToArray();
        }

        // 比特流转尺寸结构体（需要64位）
        public static Size BitsToSize(IEnumerable<bool> bits, Endianness endian = Endianness.BigEndian)
        {
            var bitArray = bits.Take(64).ToArray();
            if (bitArray.Length < 64)
                throw new ArgumentException("需要至少64位数据");

            int width = BitsToInt(bitArray.Take(32), endian);
            int height = BitsToInt(bitArray.Skip(32).Take(32), endian);
            return new Size(width, height);
        }
    }
}
